#ifndef LINUX_TASK_H
#define LINUX_TASK_H

#include <types.h>
#include <list.h>

#define EFLAGS_DEFAULT  (1 << 1)
#define EFLAGS_IF       (1 << 9)

typedef struct tss_t
{
    uint32_t pre_link;
    uint32_t esp0, ss0, esp1, ss1, esp2, ss2;
    uint32_t cr3;
    uint32_t eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
    uint32_t es, cs, ss, ds, fs, gs;
    uint32_t ldt;
    uint32_t iomap;
} _packed tss_t;

#define TASK_NAME_SIZE      32
#define TASK_DEFAULT_TICKS  10

#define TASK_LEVEL_SYSTEM   (1 << 0)
#define TASK_LEVEL_USER     (1 << 1)

typedef struct task_s task_t;

// 基于TSS的任务
struct task_s
{
    enum {
        TASK_CREATED,
        TASK_RUNNING,
        TASK_SLEEP,
        TASK_READY,
        TASK_WAITING
    } state;

    char name[TASK_NAME_SIZE];
    // 执行队列
    list_node_t running_node;
    // 任务队列
    list_node_t task_node;
    // 等待队列
    list_node_t wait_node;
    // TSS
    tss_t tss;
    // TSS选择子
    int selector;
    // 任务时间片
    uint32_t ticks;
    uint32_t slices;
    // 延时
    uint32_t sleep;
    // 任务ID
    uint32_t pid;
    // 父任务
    task_t *parent;
};

// 基于手动建栈的任务
typedef struct simple_task_t
{
    uint32_t *stack;
    int selector;
} simple_task_t;

typedef struct task_queue_t
{
    list_t ready_list;
    list_t task_list;
    list_t sleep_list;
    // 默认（系统）任务
    task_t default_task;
    // 空闲任务
    task_t idle_task;
    // 当前任务指针
    task_t *running_task;
    // 应用级代码段选择子
    uint32_t uc_selector;
    // 应用级数据段选择子
    uint32_t ud_selector;
} task_queue_t;

typedef struct task_args_t
{
    uint32_t ret_addr;
    uint32_t argc;
    char **argv;
} task_args_t;


void init_task_queue();

void init_default_task();

task_t *get_default_task();

int init_tss(task_t *task, uint32_t flag, uint32_t entry, uint32_t esp);

void start_task(task_t *task);

int init_task(task_t *task, const char *name, uint32_t flag, uint32_t entry, uint32_t esp);

void init_simple_task(simple_task_t *task, uint32_t entry, uint32_t esp);

void task_destory(task_t *task);

void task_set_ready(task_t *task);

void task_set_block(task_t *task);

void task_set_sleep(task_t *task, uint32_t ticks);

void task_set_wakeup(task_t *task);

void task_switch(task_t *from, task_t *to);

task_t *get_running_task();

void task_dispatch();

void task_time_tick();

void simple_task_switch(simple_task_t *from, simple_task_t *to);

void task_sys_sleep(uint32_t ms);

void task_sys_yield();

uint32_t task_sys_getpid();

int task_sys_fork();

int task_sys_execve(char *name, char *argv[], char *env[]);

#endif